const { getEngine } = require("./engine");
const FormData = require("form-data");
const fs = require("fs");

class FeishuSender {
  constructor(payload) {
    const { appId, appSecret, pushUrl } =
      typeof payload === "string" ? { pushUrl: payload } : payload;
    this.appId = appId;
    this.appSecret = appSecret;
    this.url = pushUrl;
  }

  ensureTenantAuth() {
    this.tenant_access_token = getEngine()(
      "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal",
      {
        method: "POST",
        data: {
          app_id: this.appId,
          app_secret: this.appSecret,
        },
      }
    ).then(({ data: { tenant_access_token } }) => tenant_access_token);

    return this;
  }

  uuid() {
    return Math.random().toString().slice(3);
  }

  async replyText(message_id, text) {
    return getEngine()(
      `https://open.feishu.cn/open-apis/im/v1/messages/${message_id}/reply`,
      {
        method: "POST",
        headers: {
          Authorization: `Bearer ${await this.tenant_access_token}`,
        },
        data: {
          msg_type: "text",
          content: JSON.stringify({ text }),
          uuid: this.uuid(),
        },
      }
    );
  }

  send(params) {
    return getEngine()(this.url, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      data: params,
    });
  }

  sendRaw(raw) {
    return this.send(raw);
  }

  async getUserId(mobile) {
    return getEngine()(
      `https://open.feishu.cn/open-apis/contact/v3/users/batch_get_id?user_id_type=${"open_id"}`,
      {
        method: "POST",
        headers: {
          Authorization: `Bearer ${await this.tenant_access_token}`,
          "Content-Type": "application/json; charset=utf-8",
        },
        data: JSON.stringify({
          mobiles: [mobile],
        }),
      }
    );
  }

  async sendApp(openId, params) {
    return getEngine()(
      "https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=open_id",
      {
        method: "POST",
        headers: {
          Authorization: `Bearer ${await this.tenant_access_token}`,
          "Content-Type": "application/json",
        },
        data: JSON.stringify({
          receive_id: openId,
          ...params,
          uuid: this.uuid(),
        }),
      }
    );
  }
  async sendAppMessage(openId, text) {
    return this.sendApp(openId, {
      msg_type: "text",
      content: JSON.stringify({ text }),
    });
  }

  async sendAppImageMessage(openId, imageKey) {
    return this.sendApp(openId, {
      msg_type: "image",
      content: JSON.stringify({ image_key: imageKey }),
    });
  }

  async sendAppMultiLineMessage(openId, title, messages) {
    return this.sendApp(openId, {
      msg_type: "post",
      content: JSON.stringify({
        zh_cn: {
          title,
          content: messages,
        },
      }),
    });
  }

  async uploadImage(url) {
    return getEngine()("https://open.feishu.cn/open-apis/im/v1/images", {
      method: "POST",
      headers: {
        "Content-Type": "multipart/form-data",
        Authorization: `Bearer ${await this.tenant_access_token}`,
      },
      data: {
        image: fs.createReadStream(url),
        image_type: "message",
      },
    });
  }

  // 纯文本
  sendText(text) {
    return this.send(this.createTextParam(text));
  }

  // 多行纯文本
  sendMultiLinesText(title, content) {
    return this.send(this.createMultiLinesParam(title, content));
  }

  createTextParam(text) {
    return {
      msg_type: "text",
      content: {
        text,
      },
    };
  }

  createMultiLinesParam(title, content) {
    return {
      msg_type: "post",
      content: {
        post: {
          zh_cn: {
            title: title,
            content,
          },
        },
      },
    };
  }
}

class FeishuPusher {
  constructor() {
    this.urlByKey = new Map();
  }
  add(key, payload) {
    this.urlByKey.set(key, payload);
  }

  use(key) {
    const payload = key === "*" ? "http://unknown" : this.urlByKey.get(key);

    return new FeishuSender(payload);
  }
}

const feishu = new FeishuPusher();

module.exports = feishu;
